﻿using System;
using System.Collections.Generic;
using System.Text;
using PacMan3D.Utils;
using Tao.OpenGl;
using Tao.FreeGlut;

namespace PacMan3D.Objects
{
    public class BigFood : IRenderable, ICollidable
    {
        public Point3D Position {get; private set;}

        private RGBAColor Color;
        private RGBAColor ShadowColor;
        private float RadiusSize;

        private int Slices = 20;
        private int Stacks = 20;

        /// 
        /// BigFood Material 
        /// 
        private float[] Specular = { 1.0f, 1.0f, 1.0f, 1.0f };
        private int Shininess = 100;

        private int DisplayListId = 0;

        public BigFood(Point3D position, float radiusSize)
        {
            this.Position = position;
            this.Position.Y = radiusSize / 4.0f;
            this.RadiusSize = radiusSize / 6.0f;
            this.Color = new RGBAColor(StandardColors.Orange, 1.0f);
            this.ShadowColor = new RGBAColor(StandardColors.LightGray, 0.7f);

            this.DisplayListId = Gl.glGenLists(1);
            Gl.glNewList(this.DisplayListId, Gl.GL_COMPILE);
            Glut.glutSolidSphere(this.RadiusSize, this.Slices, this.Stacks);
            Gl.glEndList();
        }

        public override void DrawObject()
        {
            Gl.glEnable(Gl.GL_LIGHTING);
            Gl.glPushMatrix();
                Gl.glTranslatef(this.Position.X, this.Position.Y, this.Position.Z);
                Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_SPECULAR, this.Specular);
                Gl.glMateriali(Gl.GL_FRONT, Gl.GL_SHININESS, this.Shininess); 
                Gl.glColor4f(this.Color.Red, this.Color.Green, this.Color.Blue, this.Color.Alpha);
                Gl.glCallList(this.DisplayListId);
            Gl.glPopMatrix();
            Gl.glDisable(Gl.GL_LIGHTING);
        }

        /// <summary>
        /// http://www.devmaster.net/articles/projectiveshadows/
        /// </summary>
        /// <param name="shadowMatrix"></param>
        public void DrawShadow(float[] shadowMatrix)
        {
            // Step3: Turn off lights and texture mapping
            // draw the shadow as black, blended with the surface, with no lighting, and not
            // preforming the depth test
            Gl.glColor4f(this.ShadowColor.Red, this.ShadowColor.Green, this.ShadowColor.Blue, this.ShadowColor.Alpha);

            Gl.glDisable(Gl.GL_TEXTURE_2D);
            Gl.glDisable(Gl.GL_LIGHTING);

            // Step 4: Turn off depth test
            Gl.glDisable(Gl.GL_DEPTH_TEST);

            // Step 5: Enable blending
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glBlendFunc(Gl.GL_ONE, Gl.GL_ONE_MINUS_SRC_ALPHA);

            // draw the shadow
            Gl.glPushMatrix();
                // Step 6: Render all objects that you want to cast shadows
                // project the cube through the shadow matrix
                Gl.glMultMatrixf(shadowMatrix);
                Gl.glTranslatef(this.Position.X, this.Position.Y, this.Position.Z);
                Gl.glCallList(this.DisplayListId);
            Gl.glPopMatrix();

            // Step 7: Restore old settings
            Gl.glEnable(Gl.GL_DEPTH_TEST);
            Gl.glDisable(Gl.GL_BLEND);
        }


        #region ICollidable Members

        public float Size
        {
            get { return this.RadiusSize; }
        }

        #endregion
    }
}
